package cn.yuanqiao.cqbc.util;
/**
 * @author 赵常飞
 * @date 2024/6/14 15:05
 */

import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *@Author: 赵常飞
 *@Date: 2024/6/14 15:05
 *@Description:
 *@Note:
 */

public class MD5Util {
    public static final int BUFFER = 2048;
    protected static MessageDigest messagedigest;
    protected static char[] hexDigits_5;
    private static List<File> dic;
    private static final String[] hexDigits;
    private static final int CACHE_SIZE = 2048;

    static {
        MD5Util.messagedigest = null;
        MD5Util.hexDigits_5 = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        try {
            MD5Util.messagedigest = MessageDigest.getInstance("MD5");
        }
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        MD5Util.dic = null;
        hexDigits = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
    }

    public static boolean isMatch(final String regex, final String orginal) {
        if (orginal == null || orginal.trim().equals("")) {
            return false;
        }
        final Pattern pattern = Pattern.compile(regex);
        final Matcher isNum = pattern.matcher(orginal);
        return isNum.matches();
    }

    public static boolean isNumeric(final String strValue) {
        for (int i = 0; i < strValue.length(); ++i) {
            if (!Character.isDigit(strValue.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    public static boolean isNull(final Object obj) {
        return obj == null || "".equals(obj);
    }

    public static boolean notNull(final Object obj) {
        return obj != null && !"".equals(obj.toString());
    }

    public static String md5Encode(final byte[] b, final String algorithm) {
        String resultString = null;
        try {
            final MessageDigest md = MessageDigest.getInstance(algorithm);
            resultString = byteArrayToHexString(md.digest(b));
        }
        catch (Exception ex) {
            resultString = null;
        }
        return resultString;
    }

    public static String md5Encode(final String str, final String algorithm) {
        return md5Encode(str.getBytes(), algorithm);
    }

    public static String md5Encode(final File file, final String algorithm) {
        String md5 = "";
        if (file.exists() && file.isFile()) {
            //md5 = getFileMD5String(file);
            try {
                md5=generateFileMD5(file.getAbsolutePath());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else if (file.exists() && file.isDirectory()) {
            MD5Util.dic = new ArrayList<File>();
            readDirectory(file);
            FileInputStream in = null;
            try {
                final byte[] b = new byte[1024];
                final MessageDigest md6 = MessageDigest.getInstance(algorithm);
                for (final File f : MD5Util.dic) {
                    if (!"\u8bf4\u660e\u6587\u4ef6".equals(f.getName())) {
                        in = new FileInputStream(f);
                        while (in.read(b) != -1) {
                            md6.update(b);
                        }
                        in.close();
                    }
                }
                md5 = byteArrayToHexString(md6.digest());
            }
            catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            catch (FileNotFoundException e2) {
                e2.printStackTrace();
            }
            catch (IOException e3) {
                e3.printStackTrace();
            }
            finally {
                try {
                    if (in != null) {
                        in.close();
                        in = null;
                    }
                }
                catch (Exception e4) {
                    e4.printStackTrace();
                }
            }
            try {
                if (in != null) {
                    in.close();
                    in = null;
                }
            }
            catch (Exception e4) {
                e4.printStackTrace();
            }
        }
        return md5;
    }

    public static String getFileMD5String(final File file) {
        FileInputStream in = null;
        FileChannel ch = null;
        try {
            in = new FileInputStream(file);
            ch = in.getChannel();
            final MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0L, file.length());
            MD5Util.messagedigest.update(byteBuffer);
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        catch (IOException e2) {
            e2.printStackTrace();
        }
        finally {
            if (notNull(ch)) {
                try {
                    ch.close();
                }
                catch (IOException e3) {
                    e3.printStackTrace();
                }
            }
            if (notNull(in)) {
                try {
                    in.close();
                }
                catch (IOException e3) {
                    e3.printStackTrace();
                }
            }

        }
        if (notNull(ch)) {
            try {
                ch.close();
            }
            catch (IOException e3) {
                e3.printStackTrace();
            }
        }
        if (notNull(in)) {
            try {
                in.close();
            }
            catch (IOException e3) {
                e3.printStackTrace();
            }
        }
        System.gc();
        return bufferToHex(MD5Util.messagedigest.digest());
    }

    public static String generateFileMD5(String filePath) throws Exception {
        String md5 = "";
        File file = new File(filePath);
        if (file.exists()) {
            MessageDigest messageDigest = getMD5();
            InputStream in = new FileInputStream(file);
            byte[] cache = new byte[CACHE_SIZE];
            int nRead = 0;
            while ((nRead = in.read(cache)) != -1) {
                messageDigest.update(cache, 0, nRead);
            }
            in.close();
            byte data[] = messageDigest.digest();
            md5 = byteArrayToHexString(data);
        }
        return md5;
    }

    private static MessageDigest getMD5() throws NoSuchAlgorithmException {
        return MessageDigest.getInstance("MD5");
    }

    private static String bufferToHex(final byte[] bytes) {
        return bufferToHex(bytes, 0, bytes.length);
    }

    private static String bufferToHex(final byte[] bytes, final int m, final int n) {
        final StringBuffer stringbuffer = new StringBuffer(2 * n);
        for (int k = m + n, l = m; l < k; ++l) {
            appendHexPair(bytes[l], stringbuffer);
        }
        return stringbuffer.toString();
    }

    private static void appendHexPair(final byte bt, final StringBuffer stringbuffer) {
        final char c0 = MD5Util.hexDigits_5[(bt & 0xF0) >> 4];
        final char c2 = MD5Util.hexDigits_5[bt & 0xF];
        stringbuffer.append(c0);
        stringbuffer.append(c2);
    }

    private static void readDirectory(final File directory) {
        final File[] nodeFiles = directory.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(final File dir, final String name) {
                boolean result = true;
                if (name.endsWith(".md5") ||
                        name.equalsIgnoreCase("\u6587\u4ef6\u6821\u9a8c\u7801.md5") || name.equalsIgnoreCase("\u683c\u5f0f\u5305\u6821\u9a8c\u7801.md5") || name.equalsIgnoreCase(".DS_Store") || name.equalsIgnoreCase("\u7535\u5b50\u6863\u6848\u79fb\u4ea4\u4e0e\u63a5\u6536\u767b\u8bb0\u8868.pdf") || name.equalsIgnoreCase("\u7535\u5b50\u6863\u6848\u79fb\u4ea4\u4e0e\u63a5\u6536\u767b\u8bb0\u8868.xml")) {
                    result = false;
                }
                return result;
            }
        });
        final List<File> fileList = new ArrayList<File>();
        Collections.addAll(fileList, nodeFiles);
        Collections.sort(fileList, new Comparator<File>() {
            @Override
            public int compare(final File o1, final File o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        for (final File file : fileList) {
            if (file.isDirectory()) {
                readDirectory(file);
            }
            else {
                MD5Util.dic.add(file);
            }
        }
    }

    public static String byteArrayToHexString(final byte[] b) {
        final StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; ++i) {
            resultSb.append(byteToHexString(b[i]));
        }
        return resultSb.toString();
    }

    private static String byteToHexString(final byte b) {
        int n = b;
        if (n < 0) {
            n += 256;
        }
        final int d1 = n / 16;
        final int d2 = n % 16;
        return String.valueOf(MD5Util.hexDigits[d1]) + MD5Util.hexDigits[d2];
    }

    public static boolean isAcronym(final String word) {
        for (int i = 0; i < word.length(); ++i) {
            final char c = word.charAt(i);
            if (!Character.isLowerCase(c)) {
                return false;
            }
        }
        return true;
    }

    public static boolean isNotAcronym(final String word) {
        for (int i = 0; i < word.length(); ++i) {
            final char c = word.charAt(i);
            if (Character.isLowerCase(c)) {
                return false;
            }
        }
        return true;
    }

    public static boolean isChineseChar(final String str) {
        boolean temp = false;
        final Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
        final Matcher m = p.matcher(str);
        if (m.find()) {
            temp = true;
        }
        return temp;
    }

    public static Map<String, String> readProp(final File file) {
        final Map<String, String> prop = new HashMap<String, String>();
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "gbk"));
            String line = null;
            while ((line = reader.readLine()) != null) {
                final String str = line.trim();
                if (!"".equals(str) && str.split("=").length == 2) {
                    prop.put(str.split("=")[0].trim(), str.split("=")[1].trim());
                }
                else {
                    if ("".equals(str) || str.split("=").length != 1) {
                        continue;
                    }
                    prop.put(str.split("=")[0].trim(), "");
                }
            }
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        catch (Exception e2) {
            e2.printStackTrace();
        }
        finally {
            try {
                if (reader != null) {
                    reader.close();
                    reader = null;
                }
            }
            catch (IOException e3) {
                e3.printStackTrace();
            }
        }
        try {
            if (reader != null) {
                reader.close();
                reader = null;
            }
        }
        catch (IOException e3) {
            e3.printStackTrace();
        }
        return prop;
    }

    public static String md5Encode(final byte[] b) {
        String resultString = null;
        try {
            final MessageDigest md = MessageDigest.getInstance("MD5");
            resultString = byteArrayToHexString(md.digest(b));
        }
        catch (Exception ex) {
            resultString = null;
        }
        return resultString;
    }

    public static String md5Encode(final String str) {
        return md5Encode(str.getBytes());
    }
}
